﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
using Windows.ApplicationModel.Activation;
using Windows.Foundation.Collections;
using Windows.Media.Playback;
using Windows.Storage;
using Windows.Storage.Pickers;

namespace FLAC_WinRT.Example.App.ViewModels
{
    public sealed class MainViewModel : INotifyPropertyChanged, IContinuable
    {
        private readonly RelayCommand _updateSongsListCommand;
        private readonly RelayCommand _playSelectedSongCommand;
        private readonly ObservableCollection<StorageFile> _songsCollection;
        private StorageFile _selectedSong;
        private bool _isBackgroundPlayerStarted;

        public MainViewModel()
        {
            _songsCollection = new ObservableCollection<StorageFile>();
            _updateSongsListCommand = new RelayCommand(UpdateSongsList);
            _playSelectedSongCommand = new RelayCommand(PlaySelectedSong, () => SelectedSong != null);
        }
        
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }

        public ICommand UpdateSongsListCommand
        {
            get { return _updateSongsListCommand; }
        }

        public ICommand PlaySelectedSongCommand
        {
            get { return _playSelectedSongCommand; }
        }

        public ObservableCollection<StorageFile> SongsCollection
        {
            get { return _songsCollection; }
        }

        public StorageFile SelectedSong
        {
            get { return _selectedSong; }
            set
            {
                _selectedSong = value;
                _playSelectedSongCommand.RaiseCanExecuteChanged();
            }
        }

        private async void UpdateSongsList()
        {
            await Task.Delay(1000);

            var folderPicker = new FolderPicker();
            if (ContinuationManager.Register(this, folderPicker.ContinuationData))
            {
                folderPicker.FileTypeFilter.Add(".flac");
                folderPicker.PickFolderAndContinue();
            }
        }

        private async void PlaySelectedSong()
        {
            if (SelectedSong == null)
                return;

            if (!_isBackgroundPlayerStarted)
            {
                var autoResetEvent = new AutoResetEvent(false);
                BackgroundMediaPlayer.MessageReceivedFromBackground += (o1, e1) =>
                {
                    if (e1.Data.ContainsKey("BackgroundPlayerStarted"))
                    {
                        autoResetEvent.Set();
                    }
                };

                _isBackgroundPlayerStarted = await Task.Factory.StartNew(() => autoResetEvent.WaitOne(2000));
            }

            if (_isBackgroundPlayerStarted)
            {
                BackgroundMediaPlayer.SendMessageToBackground(new ValueSet { { "AddTrack", SelectedSong.Path } });
            }
        }

        public async void Continue(IContinuationActivatedEventArgs e)
        {
            var folderPickerContinuation = e as FolderPickerContinuationEventArgs;
            if (folderPickerContinuation == null)
                throw new ArgumentException("Invalid continuation.", "e");

            var musicFiles = await KnownFolders.MusicLibrary.GetFilesAsync();

            var flacFilesSelector = new Func<StorageFile, bool>(f => f.FileType.Equals(".flac", StringComparison.OrdinalIgnoreCase));

            if (folderPickerContinuation.Folder == null)
                return;

            if (folderPickerContinuation.Folder.Name != "Music")
            {
                var folderFiles = await folderPickerContinuation.Folder.GetFilesAsync();
                var folderFlacFiles = folderFiles.Where(flacFilesSelector).ToList();
                foreach (var flacFile in folderFlacFiles)
                {
                    if (!musicFiles.Any(f => f.Name.Equals(flacFile.Name, StringComparison.OrdinalIgnoreCase)))
                        await flacFile.CopyAsync(KnownFolders.MusicLibrary);
                }
            }

            musicFiles = await KnownFolders.MusicLibrary.GetFilesAsync();
            var flacFiles = musicFiles.Where(flacFilesSelector).ToList();

            foreach (var flacFile in flacFiles)
            {
                SongsCollection.Add(flacFile);
            }
        }
    }
}
